from abc import ABC, abstractmethod
from typing import List, Dict, Any, Type, TypeVar, Generic, Optional, Union, Callable, get_type_hints
from peewee import Model, ModelSelect, Expression, OP, fn
import inspect

T = TypeVar('T', bound=Model)

class ModelField:
    """模型字段引用"""
    def __init__(self, field_name: str):
        self.field_name = field_name
    
    def __call__(self, model_class: Type[Model]):
        return getattr(model_class, self.field_name)


class QueryCondition:
    """查询条件封装类"""
    def __init__(self, model_class: Type[Model] = None):
        self.conditions = []
        self.model_class = model_class
    
    def eq(self, field_ref: Union[Callable, str, ModelField], value: Any) -> 'QueryCondition':
        """等于条件"""
        self._add_condition(field_ref, OP.EQ, value)
        return self
    
    def ne(self, field_ref: Union[Callable, str, ModelField], value: Any) -> 'QueryCondition':
        """不等于条件"""
        self._add_condition(field_ref, OP.NE, value)
        return self
    
    def in_(self, field_ref: Union[Callable, str, ModelField], values: List[Any]) -> 'QueryCondition':
        """包含条件"""
        self._add_condition(field_ref, OP.IN, values)
        return self
    
    def not_in(self, field_ref: Union[Callable, str, ModelField], values: List[Any]) -> 'QueryCondition':
        """不包含条件"""
        self._add_condition(field_ref, OP.NOT_IN, values)
        return self
    
    def gt(self, field_ref: Union[Callable, str, ModelField], value: Any) -> 'QueryCondition':
        """大于条件"""
        self._add_condition(field_ref, OP.GT, value)
        return self
    
    def gte(self, field_ref: Union[Callable, str, ModelField], value: Any) -> 'QueryCondition':
        """大于等于条件"""
        self._add_condition(field_ref, OP.GTE, value)
        return self
    
    def lt(self, field_ref: Union[Callable, str, ModelField], value: Any) -> 'QueryCondition':
        """小于条件"""
        self._add_condition(field_ref, OP.LT, value)
        return self
    
    def lte(self, field_ref: Union[Callable, str, ModelField], value: Any) -> 'QueryCondition':
        """小于等于条件"""
        self._add_condition(field_ref, OP.LTE, value)
        return self
    
    def like(self, field_ref: Union[Callable, str, ModelField], value: str) -> 'QueryCondition':
        """模糊匹配条件"""
        self._add_condition(field_ref, OP.LIKE, f"%{value}%")
        return self
    
    def _add_condition(self, field_ref: Union[Callable, str, ModelField], op: str, value: Any):
        """添加条件"""
        if isinstance(field_ref, str):
            if self.model_class:
                field_getter = lambda m: getattr(m, field_ref)
            else:
                raise ValueError("如果使用字符串字段名，必须指定model_class")
        else:
            field_getter = field_ref
        
        self.conditions.append((field_getter, op, value))


class ModelFieldFactory:
    """模型字段工厂，用于创建字段引用"""
    def __init__(self, model_class: Type[Model]):
        self.model_class = model_class
        
        # 自动为模型的所有字段创建字段引用
        for field_name in model_class._meta.fields.keys():
            # 转换为驼峰命名的getter方法
            getter_name = f"get{''.join(word.capitalize() for word in field_name.split('_'))}"
            setattr(self, getter_name, ModelField(field_name))


class BaseDao(ABC):
    """数据访问对象基类"""
    
    @property
    @abstractmethod
    def model_class(self) -> Type[Model]:
        """返回对应的模型类"""
        pass
    
    @property
    def fields(self) -> ModelFieldFactory:
        """返回模型字段工厂"""
        return ModelFieldFactory(self.model_class)
    
    def create_query_condition(self) -> QueryCondition:
        """创建查询条件对象"""
        return QueryCondition(self.model_class)
    
    def _build_query(self, condition: Optional[QueryCondition] = None) -> ModelSelect:
        """构建查询对象"""
        query = self.model_class.select()
        
        if condition:
            for field_getter, op, value in condition.conditions:
                # 获取字段名
                field = field_getter(self.model_class)
                
                # 根据操作符构建表达式
                if op == OP.EQ:
                    expr = (field == value)
                elif op == OP.NE:
                    expr = (field != value)
                elif op == OP.IN:
                    expr = (field.in_(value))
                elif op == OP.NOT_IN:
                    expr = (field.not_in(value))
                elif op == OP.GT:
                    expr = (field > value)
                elif op == OP.GTE:
                    expr = (field >= value)
                elif op == OP.LT:
                    expr = (field < value)
                elif op == OP.LTE:
                    expr = (field <= value)
                elif op == OP.LIKE:
                    expr = (field.contains(value))
                else:
                    continue
                
                query = query.where(expr)
        
        return query
    
    def query(self, condition: Optional[QueryCondition] = None) -> List[T]:
        """
        根据条件查询数据
        :param condition: 查询条件
        :return: 查询结果列表
        """
        query = self._build_query(condition)
        return list(query)
    
    def query_one(self, condition: Optional[QueryCondition] = None) -> Optional[T]:
        """
        查询单条数据
        :param condition: 查询条件
        :return: 查询结果或None
        """
        query = self._build_query(condition)
        try:
            return query.get()
        except self.model_class.DoesNotExist:
            return None
        except Exception as e:
            raise
    
    def count(self, condition: Optional[QueryCondition] = None) -> int:
        """
        统计符合条件的数据数量
        :param condition: 查询条件
        :return: 数据数量
        """
        query = self._build_query(condition)
        return query.count()
    
    def exists(self, condition: QueryCondition) -> bool:
        """
        检查是否存在符合条件的数据
        :param condition: 查询条件
        :return: 是否存在
        """
        return self.count(condition) > 0
    
    def query_by_field(self, field_name: str, field_value: Any) -> List[T]:
        """
        根据字段名和值查询数据
        :param field_name: 字段名
        :param field_value: 字段值
        :return: 查询结果列表
        """
        condition = self.create_query_condition().eq(field_name, field_value)
        return self.query(condition)
    
    def query_one_by_field(self, field_name: str, field_value: Any) -> Optional[T]:
        """
        根据字段名和值查询单条数据
        :param field_name: 字段名
        :param field_value: 字段值
        :return: 查询结果或None
        """
        condition = self.create_query_condition().eq(field_name, field_value)
        return self.query_one(condition)
    
    def query_by_fields_in(self, field_name: str, field_values: List[Any]) -> List[T]:
        """
        根据字段名和多个值查询数据（IN查询）
        :param field_name: 字段名
        :param field_values: 字段值列表
        :return: 查询结果列表
        """
        condition = self.create_query_condition().in_(field_name, field_values)
        return self.query(condition)
    
    def query_by_code(self, code_field_name: str, code: str) -> Optional[T]:
        """
        根据代码字段查询单条数据
        :param code_field_name: 代码字段名
        :param code: 代码值
        :return: 查询结果或None
        """
        return self.query_one_by_field(code_field_name, code)
    
    def query_by_group(self, group_field_name: str, group: str) -> List[T]:
        """
        根据分组字段查询数据
        :param group_field_name: 分组字段名
        :param group: 分组值
        :return: 查询结果列表
        """
        return self.query_by_field(group_field_name, group)
    
    def query_by_codes(self, code_field_name: str, codes: List[str]) -> List[T]:
        """
        根据多个代码查询数据
        :param code_field_name: 代码字段名
        :param codes: 代码列表
        :return: 查询结果列表
        """
        return self.query_by_fields_in(code_field_name, codes)
    
    @abstractmethod
    def insert_data(self, model_instance: T) -> int:
        """
        插入数据
        :param model_instance: 模型实例
        :return: 新插入记录的ID
        """
        pass
    
    @abstractmethod
    def update_data(self, model_instance: T) -> bool:
        """
        更新数据
        :param model_instance: 模型实例
        :return: 是否更新成功
        """
        pass
    
    @abstractmethod
    def delete_by_id(self, record_id: Any) -> bool:
        """
        根据ID删除数据
        :param record_id: 记录ID
        :return: 是否删除成功
        """
        pass 